using System;
using System.Collections.Generic;
using System.Web;

using MvcCms.Data;
using MvcCms.Data.Entities;

using MvcCms.Service.Cache;
using MvcCms.Service.Validation;
using MvcCms.Service.Logging;
using Microsoft.Practices.ServiceLocation;
using MvcCms.Service.Code;

namespace MvcCms.Service.CMSCode
{
    public class AccountService : IAccountService
    {
        #region Constructors

        private readonly IEntityAccountRepository _accountRepository;
        private readonly ICacheService _cacheService;
        private readonly IValidationDictionary _validationDictionary;

        public AccountService(IValidationDictionary validationDictionary,
                              IEntityAccountRepository repository, ICacheService cacheService)
        {
            _validationDictionary = validationDictionary;
            _accountRepository = repository;
            _cacheService = cacheService;
        }

        #endregion

        #region Validation Methods

        public bool ValidateUser(User userToValidate)
        {
            if (userToValidate.UserName.Trim().Length == 0)
            {
                return false;
            }
            return true;
        }

        public bool ValidateProfile(Profile profileToValidate)
        {
            return _validationDictionary.IsValid;
        }

        #endregion

        #region User Methods

        public string GetUserName()
        {
            var currentContext = HttpContext.Current;
            if (currentContext.User == null) { return null; }
            if (currentContext.User.Identity == null) { return null; }
            if (!currentContext.User.Identity.IsAuthenticated) { return null; }
            return currentContext.User.Identity.Name;
        }

        public User GetUser()
        {
            var userName = GetUserName();
            if (userName == null) { return null; }
            var user = GetUser(userName);
            user.LastActivityDate = DateTime.Now;
            EditUser(user);
            return user;
        }

        public User GetUser(Guid userId)
        {
            return _accountRepository.GetUser(userId);
        }

        public bool CreateUser(User userToCreate)
        {
            var portalRepository = ServiceLocator.Current.GetInstance<IPortalRepository>();

            var portal = portalRepository.GetPortal(_cacheService.GetCurrentPortal().PortalID);
            userToCreate.Portal = portal;
            // Validation logic
            if (!ValidateUser(userToCreate))
                return false;

            // Database logic
            try
            {
                userToCreate.UserName = userToCreate.UserName.TryTrim();
                userToCreate.Email = userToCreate.Email.TryTrim();
                userToCreate.PasswordAnswer = userToCreate.PasswordAnswer.TryTrim();
                userToCreate.PasswordQuestion = userToCreate.PasswordQuestion.TryTrim();
                _accountRepository.CreateUser(userToCreate);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }

        public IEnumerable<User> ListUsers(int pageIndex, int pageSize)
        {
            return _accountRepository.ListUsers(pageIndex, pageSize, _cacheService.GetCurrentPortal());
        }

        public IEnumerable<User> ListUsers()
        {
            return _accountRepository.ListUsers(_cacheService.GetCurrentPortal());
        }
        public IEnumerable<User> ListUsersWithProfile()
        {
            return _accountRepository.ListUsersWithProfile(_cacheService.GetCurrentPortal());
        }
        public IEnumerable<User> ListUsers4Ajax()
        {
            return _accountRepository.ListUsers(_cacheService.GetCurrentPortal());
        }
        public IEnumerable<User> SearchUsers4Ajax(string columnName, string searchTerm)
        {
            return _accountRepository.SearchUsers(columnName, searchTerm, _cacheService.GetCurrentPortal());
        }

        public IEnumerable<DTOContributor> ListContributors()
        {
            return _accountRepository.ListContributors(_cacheService.GetCurrentPortal());
        }

        public int GetNumberOfUsersOnline(int timewindow)
        {
            return _accountRepository.GetNumberOfUsersOnline(timewindow, _cacheService.GetCurrentPortal());
        }

        public User GetUser(string userName)
        {
            return _accountRepository.GetUser(userName);
        }
        public User GetUserByOpenId(string openId)
        {
            return _accountRepository.GetUserByOpenId(openId, _cacheService.GetCurrentPortal().PortalID);
        }
        public User GetUser_MPCtxt(Guid userId)
        {
            return _accountRepository.GetUser_MPCtxt(userId);
        }

        public User GetUser_MPCtxt(string userName)
        {
            return _accountRepository.GetUser_MPCtxt(userName);
        }

        public User GetUserByEmail(string email)
        {
            return _accountRepository.GetUserByEmail(email);
        }
        public bool EditUserEntity(User userToEdit)
        {
            // Validation logic
            if (!ValidateUser(userToEdit))
                return false;

            // Database logic
            try
            {
                _accountRepository.EditUserEntity(userToEdit);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }
        public bool EditUser(User userToEdit)
        {
            // Validation logic
            if (!ValidateUser(userToEdit))
                return false;

            // Database logic
            try
            {
                userToEdit.UserName = userToEdit.UserName.TryTrim();
                userToEdit.Email = userToEdit.Email.TryTrim();
                userToEdit.PasswordAnswer = userToEdit.PasswordAnswer.TryTrim();
                userToEdit.PasswordQuestion = userToEdit.PasswordQuestion.TryTrim();
                _accountRepository.EditUser(userToEdit);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }

        public bool DeleteUser(string userName)
        {
            try
            {
                _accountRepository.DeleteUser(userName);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }
        #endregion
        #region Profile Methods

        public Profile GetProfile(Guid userKey)
        {
            return _accountRepository.GetProfile(userKey);
        }
        public Profile GetProfile(int profileId)
        {
            return _accountRepository.GetProfile(profileId);
        }
        public bool SetProfileData(Profile profileToEdit)
        {
            if (!ValidateProfile(profileToEdit))
                return false;
            // Database logic
            try
            {
                _accountRepository.SetProfileData(profileToEdit);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error(GeneralMethods.GetStackNames(), ex);
                return false;
            }
            return true;
        }

        #endregion

        #region Role Methods

        public Role GetRole(string loweredRoleName)
        {
            return _accountRepository.GetRole(loweredRoleName);
        }
        public Role GetRole(Guid roleId)
        {
            return _accountRepository.GetRole(roleId);
        }
        public IEnumerable<DTOUserRole> ListUsersInRole(string roleName)
        {
            return _accountRepository.ListUsersInRole(roleName, _cacheService.GetCurrentPortal().PortalID);
        }
        public IEnumerable<User> ListUsersNotInRole(string roleName)
        {
            return _accountRepository.ListUsersNotInRole(roleName, _cacheService.GetCurrentPortal().PortalID);
        }
        #endregion
    }
}